home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / System 7.0 Samples / Edition Manager / Publish.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-26  |  30.4 KB  |  744 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2.  *
  3.  *  Apple Developer Technical Support
  4.  *
  5.  *  Edition publishing routines
  6.  *
  7.  *  Program:    EditionSample
  8.  *  File:       Publish.c - C Source
  9.  *
  10.  *  by:         C.K. Haun <TR>
  11.  *
  12.  *  Copyright © 1990,1991 Apple Computer, Inc.
  13.  *  All rights reserved.
  14.  *
  15.  *------------------------------------------------------------------------------
  16.  * Publish handles most of the publishing housekeeping.  There is (are) 
  17.  * some routines that are common to both publishing and subscribing, they 
  18.  * are located in Subscribe.c 
  19.  *----------------------------------------------------------------------------*/
  20. #define __PUBLISH__
  21.  
  22. #pragma segment Publish
  23. #pragma load "EdSampheaders"                                /* see the Buildheaders.c file */
  24.  
  25. #include "EdSampdefines.h"
  26.  
  27. /* prototypes */
  28. OSErr CreatePublisher(OSType typeToMake,Boolean fromEvent,AliasHandle theAlias);
  29. PicHandle MyMakePicture(Rect *thisRect);
  30. OSErr MyWriteSection(SectionHandle secHandle, Handle theData, OSType theType);
  31. OSErr MyUpdateEdition(SectionHandle theSection);
  32. void StorePublisher(windowCHandle shortName, SectionHandle storeSection, Rect *inRect, textSectionHandle textIn, OSType typeIn);
  33. WindowPtr FindSection(SectionHandle inSection);
  34. pascal OSErr AEWriteSectionHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  35. pascal OSErr AECreatePubHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
  36. pascal short ExpOptHook(short itemOffset, short itemHit, DialogPtr theDialog, Ptr yourDataPtr);
  37. pascal Boolean ExpOptFilter(DialogPtr theDialog, EventRecord *theEvent, short itemOffset, short *itemHit, Ptr yourDataPtr);
  38. textSectionHandle GetTextSection(windowCHandle shortName, SectionType what);
  39. textSectionHandle TextSectionFromSecHandle(SectionHandle theSection);
  40.  
  41. /* external references */
  42. extern void ShowMe(Str255 in, OSErr aevtErr);
  43. extern void ChangePlane(WindowPtr twindow);
  44. extern void MyCancelSection(SectionHandle inSection, WindowPtr theWindow);
  45. extern OSErr GetSectionHandleFromEvent(AppleEvent *AEin, SectionHandle *theSection);
  46. extern Rect selectRect;
  47. extern WindowPtr gCurrentWindow;
  48. extern void SetMyCursor(short myCurs);
  49. extern void SwitchChecks(short itemNow);
  50. extern void AppendString(Str255 target, Str255 appendIt);
  51. extern Boolean gShowPub;
  52. extern Boolean gShowSub;
  53. extern Boolean gHasSelection;
  54. extern ProcessSerialNumber gOurSN;                          /* serial number of this process (us) */
  55. extern Boolean gShowingAll;
  56. /* globals */
  57. SectionHandle gSecHandle;
  58. EditionRefNum gEdRefNum;
  59. EditionContainerSpec gEdSpec;
  60. unsigned long gSectionID = 1;
  61.  
  62. /*  CreatePublisher takes the currently selected area in the current window 
  63. *       and creates an edition.  It starts by setting up some default data 
  64. *       structures and creating a preview picture.  
  65. *       Then the user is prompted for a location and name for the publisher
  66. *       with the NewPublisherDialog.  If the user clicks OK, then the edition
  67. *       is created and the section handle and rectangle for this edition is
  68. *       stored in my data structure for this window, and the first edition
  69. *       is written out.
  70. */
  71.  
  72. OSErr CreatePublisher(OSType typeToMake,Boolean fromEvent,AliasHandle theAlias)
  73. {
  74.     NewPublisherReply myreply;
  75.     Handle theData;
  76.     Rect currentRect;
  77.     textSectionHandle pubText;
  78.     Str31 addPub;
  79.     static pubCounter;
  80.     OSErr myErr;
  81.     windowCHandle shortName;
  82.     extern Point expPoint;
  83.     extern Boolean gExpanded;
  84.     /* we're publishing from the current, topmost window */
  85.     shortName = (windowCHandle)GetWRefCon(gCurrentWindow);
  86.     HLock((Handle)shortName);
  87.     switch (typeToMake) {
  88.         case 'PICT':
  89.             currentRect = (*shortName)->selectionRect;
  90.             /* take the rectangle we currently have selected, and make it a picture */
  91.             InsetRect(¤tRect, 4, 4);                  /* take away the bordering outset */
  92.             theData = (Handle)MyMakePicture(¤tRect);      /* my function to make a PICT */
  93.             /* Set up the reply record for the publisher dialog.  */
  94.             myreply.usePart = false;                        /* must be false */
  95.             myreply.previewFormat = 'PICT';                 /* type of data we're publishing */
  96.             myreply.preview = theData;                      /* handle to the pict data */
  97.             break;
  98.         case 'TEXT':
  99.             /* make text preview */
  100.             myreply.usePart = false;                        /* must be false */
  101.             myreply.previewFormat = 'TEXT';                 /* type of data we're publishing */
  102.             pubText = GetTextSection(shortName, stPublisher);
  103.             HLock((Handle)pubText);
  104.             theData = (*pubText)->theText;                  /* duplicate the text for our preview */
  105.             HandToHand(&theData);
  106.             if (GetHandleSize(theData) > 200)
  107.                 SetHandleSize(theData, 200);
  108.             
  109.             myreply.preview = theData;
  110.             break;
  111.         case kCustomType:
  112.             break;
  113.     }
  114.     GetLastEditionContainerUsed(&gEdSpec);                  /* get a new edition containter.  */
  115.     /* this call gives us a duplicate of the last used, or if none used last, gives */
  116.     /* us a default container */
  117.     /* BY THE WAY - the 'last used' means the last used by the Edition Manager, not */
  118.     /* by your application, so if you don't specify a default name then the */
  119.     /* name that comes up as the default for the edition may be the last */
  120.     /* name used by another application, or from the last time your */
  121.     /* application was run.  So if you are concerned about this (like you */
  122.     /* think it may confuse the user) set your own default */
  123.     /* As a sidelight (and not guarenteed) an alias to the last edition container used */
  124.     /* is stored in the 'Preferences' folder in the system folder */
  125.     myreply.container = gEdSpec;                            /* put our file spec in the container to be filled */
  126.     /* now set the default name to be the same as the window plus a count */
  127.     GetWTitle(gCurrentWindow, &myreply.container.theFile.name);
  128.     GetIndString(addPub, kGeneralStrings, 1);
  129.     AppendString(myreply.container.theFile.name, addPub);
  130.     NumToString((long)((*shortName)->numPubs) + 1, addPub);
  131.     AppendString(myreply.container.theFile.name, addPub);
  132.     if(!fromEvent){
  133.     if (!gExpanded)
  134.         myErr = NewPublisherDialog(&myreply);               /* run the dialog */
  135.     else
  136.         myErr = NewPublisherExpDialog(&myreply, expPoint, kExpandedDITL, (ExpDlgHookProcPtr)ExpOptHook,
  137.                                       (ExpModalFilterProcPtr)ExpOptFilter, nil);
  138.     if (myErr) {
  139.         ShowMe("\pPubisher dialog", myErr);
  140.         return;
  141.     }
  142.     if (myreply.canceled) {                                 /* they canceled.  release memory, reset our */
  143.         /* menus and cursors, and go away */
  144.         switch (typeToMake) {
  145.             case 'PICT':
  146.                 KillPicture((PicHandle)theData);
  147.                 InvalRect(&(*shortName)->selectionRect);
  148.                 gShowPub = false;
  149.                 (*shortName)->hasSelection = false;
  150.                 SetMyCursor(0);
  151.                 SwitchChecks(kSelectStuff);
  152.                 
  153.                 break;
  154.             case 'TEXT':
  155.                 DisposHandle((*pubText)->theText);
  156.                 DisposHandle((Handle)pubText);
  157.                 DisposHandle(theData);
  158.                 break;
  159.             case kCustomType:
  160.                 break;
  161.         }
  162.         return;
  163.     }}
  164.     /* They clicked Publish.  First create the container (file) to hold the data */
  165.     /* See if thye are replacing a file */
  166.     if (!myreply.replacing) {
  167.         if (myErr = CreateEditionContainerFile(&myreply.container.theFile, 'CKH6', myreply.container.theFileScript)) {
  168.             ShowMe("\pCreateEditionContainerFIle", myErr);
  169.             return;
  170.         } 
  171.         } else {
  172.         /* they agreed to delete an existing file.  Kill it. */
  173.         FSpDelete(&myreply.container.theFile);
  174.         if (myErr = CreateEditionContainerFile(&myreply.container.theFile, 'CKH6', myreply.container.theFileScript)) {
  175.             ShowMe("\pCreateEditionContainerFIle", myErr);
  176.             return;
  177.  
  178.         }
  179.     }
  180.     /* now create the section record to describe this data to the edition manager */
  181.     /*  The section handle that is returned by this function will be the */
  182.     /* way that you will reference this edition for as long as the edition is */
  183.     /* active. */
  184.     /* The main way you'll keep track is through the section ID number. */
  185.     /* In this case, I have a base ID number for the window, and I just increment */
  186.     /* my general ID (gSectionID) every time I create an edition, and add it to the window ID.  */
  187.     if (GetHandleSize((Handle)(*shortName)->fileAliasHandle) == 0) {
  188.         myErr = NewSection(&myreply.container, nil, stPublisher, (*shortName)->windowID + gSectionID, pumOnSave, &gSecHandle);
  189.         /* nil for sectionDocument if it's never been saved */
  190.     } else {
  191.         /* if the file has been saved once, then we can store a reference to the 'parent' file */
  192.         /* in the edition */
  193.         FSSpec tempSpec;
  194.         Boolean myWasChanged;
  195.         myErr = ResolveAlias(nil, ((*shortName)->fileAliasHandle), &tempSpec, &myWasChanged);
  196.         myErr = NewSection(&myreply.container, &tempSpec, stPublisher, (*shortName)->windowID + gSectionID, pumOnSave,
  197.                            &gSecHandle);
  198.         
  199.     }
  200.     if (!myErr) {
  201.         /* put the section handle into our window structure */
  202.         (*gSecHandle)->refCon = kNeverSaved;                /*            meaning that this _document_ has not been saved */
  203.         /* put what type of thing this is in the refcon of the section handle */
  204.         switch (typeToMake) {
  205.             /* This is a little kludgy because I want to */
  206.             case 'PICT':
  207.                 (*gSecHandle)->refCon = kPictType;
  208.                 break;
  209.             case 'TEXT':
  210.                 (*gSecHandle)->refCon = kTextType;
  211.                 break;
  212.         }
  213.         StorePublisher(shortName, gSecHandle, &(*shortName)->selectionRect, pubText, typeToMake);
  214.     }
  215.     /* now write the data to the container */
  216.     MyWriteSection(gSecHandle, theData, typeToMake);
  217.     HUnlock(theData);
  218.     switch (typeToMake) {
  219.         case 'PICT':
  220.             KillPicture((PicHandle)theData);
  221.             break;
  222.         case 'TEXT':
  223.             break;
  224.         case kCustomType:
  225.             break;
  226.     }
  227.     (*shortName)->hasSelection = false;
  228.     InvalRect(&(*shortName)->selectionRect);                /* get rid of border once publish has happened */
  229.     gShowPub = false;
  230.     (*shortName)->hasSelection = false;
  231.     SetMyCursor(0);
  232.     SwitchChecks(kSelectStuff);
  233.     HUnlock((Handle)shortName);
  234. }
  235.  
  236. /* end CreatePublisher */
  237.  
  238. /* MyUpdateEdition publishes the latest data for this edition.  This will
  239. * be called when the user selects 'Send Edition Now' from the options
  240. * dialog, or when the document is saved (if automatic saving is 
  241. * enabled), or if a section write AppleEvent happens
  242. */
  243. OSErr MyUpdateEdition(SectionHandle theSection)
  244. {
  245.     WindowPtr tempCurrentWindow;
  246.     WindowPtr tempWindow;
  247.     Boolean tempSub, tempPub;
  248.     windowCHandle shortName;
  249.     SectionHandle *tempPtr;
  250.     register qq;
  251.     Rect *tempRectPtr;
  252.     extern Rect gShowPubRect;
  253.     extern Rect gShowSubRect;
  254.     GetPort(&tempWindow);
  255.     tempCurrentWindow = gCurrentWindow;
  256.     if (((*theSection)->refCon & 0xf) == kPictType) {
  257.         gCurrentWindow = FindSection(theSection);
  258.         HLock((Handle)theSection);
  259.         /* kill the borders, if any are showing right now */
  260.         tempSub = gShowSub;
  261.         tempPub = gShowPub;
  262.         if (gShowSub)
  263.             InvalRect(&gShowSubRect);
  264.         if (gShowPub)
  265.             InvalRect(&gShowPubRect);
  266.         gShowSub = gShowPub = false;
  267.         SetPort(gCurrentWindow);
  268.         shortName = (windowCHandle)GetWRefCon(gCurrentWindow);
  269.         HLock((Handle)shortName);
  270.         (ProcPtr)((*shortName)->drawMe)(shortName, gCurrentWindow);     /* draw without borders */
  271.         /* search this window for the section asked for */
  272.         HLock((*shortName)->pubs);
  273.         tempPtr = (SectionHandle *)*(*shortName)->pubs;
  274.         for (qq = 0; qq < (*shortName)->numPubs; qq++) {
  275.             HLock((Handle)*tempPtr);
  276.             if ((*theSection)->sectionID == (*(*tempPtr))->sectionID) {
  277.                 PicHandle tempPic;
  278.                 /* it's this one, grab the rect, pic it, publish it, and go away */
  279.                 HLock((*shortName)->pubRects);
  280.                 tempRectPtr = (Rect *)*(*shortName)->pubRects;
  281.                 tempRectPtr += qq;
  282.                 tempPic = MyMakePicture(tempRectPtr);
  283.                 HUnlock((*shortName)->pubRects);
  284.                 MyWriteSection(*tempPtr, (Handle)tempPic, 'PICT');
  285.                 KillPicture(tempPic);
  286.                 HUnlock((Handle)*tempPtr);
  287.                 break;
  288.             }
  289.         }
  290.         HUnlock((Handle)theSection);
  291.         HUnlock((Handle)shortName);
  292.     } else {
  293.         textSectionHandle theTS = TextSectionFromSecHandle(theSection);
  294.         /* it's a text pub */
  295.         MyWriteSection(theSection, (*theTS)->theText, 'TEXT');
  296.         
  297.     }
  298.     InvalRect(&gCurrentWindow->portRect);
  299.     gCurrentWindow = tempCurrentWindow;
  300.     SetPort(tempWindow);
  301.     return(noErr);
  302. }
  303.  
  304. /* end MyUpdateEdition */
  305.  
  306. /* MyMakePicture is a handy place to create our PICT demo data item.
  307. * It's called to create the actual edition data as well as the 'preview'
  308. * picture.
  309. */
  310. PicHandle MyMakePicture(Rect *thisRect)
  311. {
  312.     PicHandle thepic;
  313.     windowCHandle drawers;
  314.     Boolean tempPub, tempSub;
  315.     RgnHandle tempClip;
  316.     /* make sure borders aren't included in the picture */
  317.     tempPub = gShowPub;
  318.     tempSub = gShowSub;
  319.     gShowPub = false;
  320.     gShowSub = false;
  321.     tempClip = NewRgn();
  322.     GetClip(tempClip);
  323.     ClipRect(thisRect);
  324.     thepic = OpenPicture(thisRect);
  325.     drawers = (windowCHandle)GetWRefCon(gCurrentWindow);
  326.     HLock((Handle)drawers);
  327.     (ProcPtr)((*drawers)->drawMe)(drawers, gCurrentWindow);
  328.     HUnlock((Handle)drawers);
  329.     ClosePicture();
  330.     SetClip(tempClip);
  331.     DisposeRgn(tempClip);
  332.     /* restore old border states */
  333.     gShowPub = tempPub;
  334.     gShowSub = tempSub;
  335.     return(thepic);
  336. }
  337.  
  338. /* end MyMakePicture */
  339.  
  340. /* AEWriteSectionHandler is the AppleEvent handler for section write
  341. * events.   It first pulls the SectionHandle out of the AppleEvent record,
  342. * then verifies that this is a registered section (still active, not canceled)
  343. * and then calls MyUpdateEdition to write the edition
  344. */
  345. pascal OSErr AEWriteSectionHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  346. {
  347. #pragma unused (reply,refIn)
  348.     SectionHandle theSection;
  349.     OSErr myErr;
  350.     myErr = GetSectionHandleFromEvent(messagein, &theSection);
  351.     if (myErr = IsRegisteredSection((SectionHandle)theSection)) {
  352.         ShowMe("\p Write IsRegisteredSection", myErr);
  353.         return(myErr);
  354.     }
  355.     MyUpdateEdition(theSection);
  356.     
  357. }
  358.  
  359. /* end AEWriteSectionHandler */
  360. /* •••• NEW EVENT •••• */
  361. /* •• Please read the description and code in the Inside Mac vol VI chapters on */
  362. /* the Edition Manager and APpleEvents for a full description */
  363. /* AECreatePubHandler handles the new create publisher event */
  364.  
  365. pascal OSErr AECreatePubHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  366. { windowCHandle tempWC;
  367. OSErr pubError = noErr;
  368. AliasHandle theAlias;
  369. Handle objectSpec;
  370. Size objectSize;
  371. DescType thisType;
  372. Size returnedSize;
  373. OSType theType;
  374. Boolean askForDialog;
  375. #define errAENoSuchObject 'noob'
  376. #define keyAEEditionFileLoc 'eloc'
  377. #define typeObjectSpecifier 'obj '
  378. /* this event has two parameters, a object specifier and an alias handle. */
  379. /* Both parameters are optional. */
  380. /* This sample application does not support the AppleEvents object model, so */
  381. /* we don't care about that parameter. */
  382. /* If you don't support the object model, then you need to check for a valid */
  383. /* current selection in the frontmost window */
  384. /* it's the same check we make to see if we should enable the 'Create Publisher' */
  385. /* menu item. */
  386. tempWC = (windowCHandle)GetWRefCon(FrontWindow());
  387. if (gHasSelection || HasTESelection(tempWC)){
  388. /* there is a valid selection. */
  389. /* get the alias handle from the event, if there is one */
  390. /* since we don't support the AE Object model yet, return an error if there is an object */
  391. /* spec contained in this event */
  392. pubError = AEGetParamPtr(messagein, keyDirectObject, typeObjectSpecifier, &thisType, (Ptr)&objectSpec,sizeof(Handle), &objectSize);
  393. if(pubError == noErr){
  394. /* no error means that there was an object specifier.  That's Bad.  return that we don't understand it */
  395. return(errAENoSuchObject);
  396. }
  397. pubError = AEGetParamPtr(messagein, keyAEEditionFileLoc, typeAlias, &thisType, (Ptr)&theAlias,sizeof(AliasHandle), &returnedSize);
  398. /* now pass to our publishing routine */
  399.  if (HasTESelection(tempWC))
  400.       theType ='TEXT';
  401.       else
  402.       theType ='PICT'; 
  403.  
  404.  
  405. pubError = CreatePublisher(theType,true,theAlias);
  406. } else {
  407. /* there was not a valid selection.  Return the errAENoSuchObject error, since this */
  408. /* makes the most sense in this situation, and when you do implement the objects you */
  409. /* will already be prepared.  Well, on one line of code at least.... */
  410. pubError= errAENoSuchObject;
  411. }
  412. return(pubError);
  413. }
  414. /* end AECreatePubHandler */
  415. /* AEScrollSectionHandler handles the scroll section event.  You'll get this
  416. * event when the user clicks 'Open Publisher' either from the 
  417. * Subcriber Options dialog, or from the Finder window.
  418. * This may also have happened after an ODOC AppleEvent, so 
  419. * don't assume anything about your state that wouldn't be true 
  420. * after an initial application launch
  421. */
  422. pascal OSErr AEScrollSectionHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  423. {
  424. #pragma unused (reply,refIn)
  425.     WindowPtr tempWindow;
  426.     SectionHandle theSection;
  427.     OSErr myErr;
  428.     myErr = GetSectionHandleFromEvent(messagein, &theSection);
  429.     tempWindow = FindSection(theSection);
  430.     /* First bring our application to the front, then */
  431.     /* treat this the same way you would a click in a back window */
  432.     SetFrontProcess(&gOurSN);
  433.     if (tempWindow != nil)
  434.         ChangePlane(tempWindow);
  435.     return(noErr);
  436. }
  437.  
  438. /* end AEScrollSectionHandler */
  439.  
  440. /* AECancelSectionHandler cancels a current section, either a publisher
  441. * or subscriber.  This function pulls the section handle out of the 
  442. * AppleEvent, then dispatches to the proper cancel routine for a
  443. * pub or sub.
  444. */
  445. pascal OSErr AECancelSectionHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  446. {
  447. #pragma unused (reply,refIn)
  448.     SectionHandle theSection;
  449.     OSErr myErr;
  450.     myErr = GetSectionHandleFromEvent(messagein, &theSection);
  451.     myErr = IsRegisteredSection(theSection);
  452.     if (myErr != noErr)
  453.         return(myErr);                                      /* already killed by someone */
  454.     MyCancelSection(theSection, FindSection(theSection));
  455.     
  456. }
  457.  
  458. /* end AECancelSectionHandler */
  459.  
  460. /* MyWriteSection actually opens and writes the section data.  This will
  461. * be called in response to a click in 'Send Edition Now' in the pub options
  462. * box, from the section event 'write section', or when the file is being saved
  463. * and 'pumAuto' is enabled
  464. */
  465. OSErr MyWriteSection(SectionHandle secHandle, Handle theData, OSType theType)
  466. {
  467.     OSErr myErr;
  468.     /* update the time in the section handle please */
  469.     /* this tells the Edition Manager that the eidtion has changed, and */
  470.     /* to alert all the subscribers to the change */
  471.     SetCursor(*GetCursor(watchCursor));
  472.     HLock((Handle)secHandle);
  473.     GetDateTime(&(*secHandle)->mdDate);                     /* ••• Please see NOTE in main.c about mdDate (find mdDate) */
  474.     HUnlock((Handle)secHandle);
  475.     /* OpenNewEdition, _NOT_ OpenEdition.  You need to use OpenNewEdition */
  476.     /* to get write access and to let the Edition Manager determine if you */
  477.     /* are allowed to write to this section */
  478.     myErr = OpenNewEdition(secHandle, 'CKH6', nil, &gEdRefNum);
  479.     if (myErr)
  480.         ShowMe("\pOpenNewEdition", myErr);
  481.     HLock(theData);
  482.     /* And actually write the data (finally) */
  483.     
  484.     myErr = WriteEdition(gEdRefNum, theType, *theData, GetHandleSize(theData));
  485.     if (myErr)
  486.         ShowMe("\pWriteEdition", myErr);
  487.     if (myErr)
  488.         myErr = 0;
  489.     else
  490.         myErr = -1;
  491.     /* The Boolean tells the Edition Manager if you were successful in */
  492.     /* writing the data. */
  493.     myErr = CloseEdition(gEdRefNum, (Boolean)myErr);
  494.     return(myErr);
  495. }
  496.  
  497. /* end MyWriteSection */
  498.  
  499. /* StorePublisher moves the window data struct storing function to here */
  500. /* shortName is locked on entry */
  501. void StorePublisher(windowCHandle shortName, SectionHandle storeSection, Rect *inRect, textSectionHandle textIn, OSType typeIn)
  502. {
  503.     Rect *tempRectPtr;
  504.     SectionHandle *tempPtr;
  505.     OSErr myErr;
  506.     switch (typeIn) {
  507.         case 'PICT':
  508.             HUnlock((*shortName)->pubs);
  509.             MySetHandleSize((*shortName)->pubs, GetHandleSize((*shortName)->pubs) + sizeof(Handle));
  510.             myErr = MemError();
  511.             if (myErr)
  512.                 ShowMe("\pMemory", myErr);
  513.             HLock((*shortName)->pubs);
  514.             tempPtr = (SectionHandle *)((*(*shortName)->pubs) + (sizeof(Handle) * ((*shortName)->numPubs)));
  515.             *tempPtr = (SectionHandle)storeSection;
  516.             /* •••• NOTE, please look at the note in the Subscribe.c file concerning the dirty flag and  */
  517.             /* editions.  Open Subscribe.c and find the string 'Human Interface' */
  518.             /*    (*shortName)->windowDirty = true;  */
  519.             /* save the rectangle to show the published rectangle if the user wants to see it. */
  520.             HUnlock((*shortName)->pubRects);
  521.             MySetHandleSize((*shortName)->pubRects, (GetHandleSize((*shortName)->pubRects) + sizeof(Rect)));
  522.             myErr = MemError();
  523.             if (myErr)
  524.                 ShowMe("\pMemory", myErr);
  525.             HLock((*shortName)->pubRects);
  526.             tempRectPtr = (Rect *)*(*shortName)->pubRects;
  527.             tempRectPtr += (*shortName)->numPubs;
  528.             *tempRectPtr = *inRect;
  529.             (*shortName)->numPubs++;
  530.             HUnlock((*shortName)->pubRects);
  531.             HUnlock((*shortName)->pubs);
  532.             break;
  533.         case 'TEXT':
  534.             /* set my text section ID to the same as the actual section ID, again, it keeps */
  535.             /* dereferencing down */
  536.             (*textIn)->theID = (*storeSection)->sectionID;
  537.             /* tell myself that this is a publisher */
  538.             (*textIn)->publishing = true;
  539.             if ((*shortName)->textSections == nil) {
  540.                 (*shortName)->textSections = textIn;
  541.             } else {
  542.                 textSectionHandle tempTS = (*shortName)->textSections;
  543.                 while ((*tempTS)->nextSection != nil) {
  544.                     tempTS = (*tempTS)->nextSection;
  545.                 }
  546.                 (*tempTS)->nextSection = textIn;
  547.             }
  548.             (*textIn)->theSection = storeSection;
  549.             break;
  550.     }
  551.     gSectionID++;
  552. }
  553.  
  554. /* Find Section returns the window that this section is included in */
  555. /* Need to look in both the PICT and TEXT lists */
  556. WindowPtr FindSection(SectionHandle inSection)
  557. {
  558.     extern WindowPtr gActionWindows;
  559.     extern short gWindowCount;
  560.     long subIDtofind;
  561.     Boolean secFound = false;
  562.     SectionHandle *tempPtr;
  563.     SectionRecord *tempRecord;
  564.     Handle tempHandle;
  565.     WindowPtr tempNextWindow;
  566.     register qq, jj;
  567.     subIDtofind = (*inSection)->sectionID;
  568.     tempNextWindow = gActionWindows;                        /* start at the beginning of the chain */
  569.     for (qq = 0; qq < gWindowCount; qq++) {
  570.         windowCHandle tempWC;
  571.         /* do housekeeping to get to the section handle list */
  572.         tempWC = (windowCHandle)GetWRefCon(tempNextWindow);
  573.         HLock((Handle)tempWC);
  574.         if (((*inSection)->refCon & 0xf) == kPictType) {
  575.             tempHandle = (*tempWC)->pubs;                   /* handle containing SectionHandles */
  576.             HLock(tempHandle);
  577.             tempPtr = (SectionHandle *)*tempHandle;
  578.             /* Loop through all our sections until we find this edition */
  579.             for (jj = 0; jj < (*tempWC)->numPubs; jj++) {
  580.                 HLock((Handle)*tempPtr);
  581.                 tempRecord = *(*tempPtr);
  582.                 if (tempRecord->sectionID == subIDtofind) {
  583.                     HUnlock((Handle)*tempPtr);
  584.                     HUnlock((Handle)tempWC);
  585.                     return(tempNextWindow);
  586.                 } else {
  587.                     HUnlock((Handle)tempWC);
  588.                     HUnlock((Handle)*tempPtr);
  589.                     tempPtr += 1;
  590.                 }
  591.             }
  592.             HUnlock(tempHandle);
  593.             /* same thing for subscribers */
  594.             tempHandle = (*tempWC)->subs;                   /* handle containing SectionHandles */
  595.             HLock(tempHandle);
  596.             tempPtr = (SectionHandle *)*tempHandle;
  597.             /* Loop through all our sections until we find this edition */
  598.             for (jj = 0; jj < (*tempWC)->numSubs; jj++) {
  599.                 HLock((Handle)*tempPtr);
  600.                 tempRecord = *(*tempPtr);
  601.                 if (tempRecord->sectionID == subIDtofind) {
  602.                     HUnlock((Handle)*tempPtr);
  603.                     HUnlock((Handle)tempWC);
  604.                     return(tempNextWindow);
  605.                 } else {
  606.                     HUnlock((Handle)tempWC);
  607.                     HUnlock((Handle)*tempPtr);
  608.                     tempPtr += 1;
  609.                 }
  610.             }
  611.             HUnlock(tempHandle);
  612.         } else {
  613.             /* Look in the TEXT lists */
  614.             if ((*tempWC)->textSections) {
  615.                 textSectionHandle tempTS = (*tempWC)->textSections;
  616.                 do {
  617.                     if ((*((*tempTS)->theSection))->sectionID == subIDtofind) {
  618.                         HUnlock((Handle)tempWC);
  619.                         return(tempNextWindow);
  620.                     }
  621.                     tempTS = (*tempTS)->nextSection;
  622.                 } while (tempTS);
  623.                 
  624.             }
  625.         }
  626.         tempNextWindow = (*tempWC)->nextWindow;
  627.         
  628.         HUnlock((Handle)tempWC);
  629.     }
  630.     return(nil);
  631. }
  632.  
  633. pascal short ExpOptHook(short itemOffset, short itemHit, DialogPtr theDialog, Ptr yourDataPtr)
  634. {
  635.     short myHit;
  636.     short itemType;
  637.     ControlHandle theButton;
  638.     Rect theRect;
  639.     /* first make sure that a sub-dialog is not frontmost */
  640.     /* so we don't filter keys or hits to a sub-dialog */
  641.     if (GetWRefCon((WindowPtr)theDialog) == 'stdf' || GetWRefCon((WindowPtr)theDialog) == 'optn') {
  642.         /* only have one item in this expansion, but we'll check the range anyway */
  643.         myHit = itemHit - itemOffset;                       /* since our item numbers are relative to the total number */
  644.         /* of items in the dialog, and the system may change.  Always do your item numbering based */
  645.         /* on the offset, this will prevent incompatability when the system dialog grows or shrinks */
  646.         if (myHit == 1) {                                   /* I only added one item, so this be the one */
  647.             /* Pass itemHit here, not myHit, since the dialog manager has no idea that this is an */
  648.             /* additive dialog.  It is counting from the actual start of the DITL, not the start of */
  649.             /* your custom items */
  650.             GetDItem(theDialog, itemHit, &itemType, (Handle *)&theButton, &theRect);
  651.             if (GetCtlValue(theButton))
  652.                 SetCtlValue(theButton, false);
  653.             else
  654.                 SetCtlValue(theButton, true);
  655.         }
  656.     }
  657.     return(itemHit);                                        /* the return value must be absolute */
  658. }
  659.  
  660. pascal Boolean ExpOptFilter(DialogPtr theDialog, EventRecord *theEvent, short itemOffset, short *itemHit, Ptr yourDataPtr)
  661. {
  662.     short myHit;
  663.     short itemType;
  664.     ControlHandle theButton;
  665.     Rect theRect;
  666.     /* first make sure that a sub-dialog is not frontmost */
  667.     /* so we don't filter keys or hits to a sub-dialog */
  668.     if (GetWRefCon((WindowPtr)theDialog) == 'stdf' || GetWRefCon((WindowPtr)theDialog) == 'optn') {
  669.         /* standard filter proc kinda stuff here */
  670.         if ((theEvent->what) == keyDown) {
  671.             char tempChar;
  672.             tempChar = theEvent->message & charCodeMask;
  673.             
  674.             if (((tempChar == 'A') || (tempChar == 'a')) && (theEvent->modifiers & cmdKey)) {
  675.                 /* they pressed an A with the command key down, we get to handle it. */
  676.                 GetDItem(theDialog, itemOffset + 1, &itemType, (Handle *)&theButton, &theRect);
  677.                 if (GetCtlValue(theButton))
  678.                     SetCtlValue(theButton, false);
  679.                 else
  680.                     SetCtlValue(theButton, true);
  681.                 
  682.                 return(true);                               /* tell folks we handled it */
  683.             }
  684.         }
  685.     }
  686.     return(false);                                          /* was not a keystroke we wanted */
  687.     
  688. }
  689.  
  690. /* shortName is locked on entry */
  691. textSectionHandle GetTextSection(windowCHandle shortName, SectionType what)
  692. {
  693.     CharsHandle theRawText;
  694.     TEHandle tempTE;
  695.     textSectionHandle theTextSection;
  696.     short theLength;
  697.     Handle theSelection;
  698.     theTextSection = (textSectionHandle)NewHandle(sizeof(textSection));
  699.     HLock((Handle)theTextSection);
  700.     (*theTextSection)->bordered = gShowingAll;              /* create section reflecting current */
  701.     /* global border state */
  702.     tempTE = (*shortName)->boxHandle;
  703.     (*theTextSection)->startChar = (*tempTE)->selStart;
  704.     if (what == stPublisher) {
  705.         /* initialize it if it's a publisher */
  706.         (*theTextSection)->endChar = (*tempTE)->selEnd;
  707.         
  708.         theRawText = TEGetText(tempTE);
  709.         theSelection = NewHandle(((*tempTE)->selEnd) - ((*tempTE)->selStart));
  710.         
  711.         HLock(theSelection);
  712.         HLock((Handle)theRawText);
  713.         BlockMove((Ptr)*theRawText + (*tempTE)->selStart, (Ptr)*theSelection, (*tempTE)->selEnd - (*tempTE)->selStart);
  714.         HUnlock(theSelection);
  715.         HUnlock((Handle)theRawText);
  716.         (*theTextSection)->theText = theSelection;
  717.     } else {
  718.         /* set start same as end for subscribers */
  719.         (*theTextSection)->endChar = (*tempTE)->selStart;
  720.         (*theTextSection)->theText = NewHandle(0);
  721.     }
  722.     (*theTextSection)->nextSection = nil;
  723.     return(theTextSection);
  724. }
  725.  
  726. textSectionHandle TextSectionFromSecHandle(SectionHandle theSection)
  727. {
  728.     windowCHandle tempWC = (windowCHandle)GetWRefCon(FindSection(theSection));      /* gets the window it's in */
  729.     textSectionHandle tempTS = (*tempWC)->textSections;
  730.     unsigned long idToFind;
  731.     
  732.     idToFind = (*theSection)->sectionID;
  733.     /* find the ID that matches this thang */
  734.     do {
  735.         if ((*tempTS)->theID == idToFind)
  736.             return(tempTS);
  737.         tempTS = (*tempTS)->nextSection;
  738.     } while (tempTS);
  739.     return(nil);                                            /* failed */
  740. }
  741.  
  742.  
  743. #undef __PUBLISH__
  744.